/**
 * interlock.c
 */

#include <signal.h>
#include <sys/time.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>

#include <Ipc.h>
#include <Base.h>
#include <Thread.h>

#include "../av/avRecThrd.h"

#include "alarmInspectsensor.h"

#include "jze/alarmMsg.h"
#include <capturer.h>
#include "alarmInterlock.h"

#define TIMER_INTERVAL_US (1000 * 500)	// 0.5s
int g_gpioFD = -1;
int g_alarm     = 0;

static AlarmGPIO m_alarmSConf = {1, true, false, 1000 * 1000, 1000 * 1000};
static AlarmGPIO m_alarmLConf = {2, true, false, 1000 * 1000, 1000 * 1000};
static int m_sigAlrmSCnt = 0;
static int m_sigAlrmLCnt = 0;
static struct itimerval m_alarmCntTimer;


/**
    not used.
*/
static void sigAlrmHandle(int sigNo) {
	int sUs = (++m_sigAlrmSCnt) * TIMER_INTERVAL_US;
	if (m_alarmSConf.enable && ((m_alarmSConf.level && sUs >= m_alarmSConf.onUs) ||
			(!m_alarmSConf.level && sUs >= m_alarmSConf.offUs))) {
		m_sigAlrmSCnt = 0;
		m_alarmSConf.level = !m_alarmSConf.level;
		setGPIOPinVal(g_gpioFD, getGPIOOutPinEnum(m_alarmSConf.addr), m_alarmSConf.level);
	}

	int lUs = (++m_sigAlrmLCnt) * TIMER_INTERVAL_US;
	if (m_alarmLConf.enable && ((m_alarmLConf.level && lUs >= m_alarmLConf.onUs) ||
			(!m_alarmLConf.level && lUs >= m_alarmLConf.offUs))) {
		m_sigAlrmLCnt = 0;
		m_alarmLConf.level = !m_alarmLConf.level;
		setGPIOPinVal(g_gpioFD, getGPIOOutPinEnum(m_alarmLConf.addr), m_alarmLConf.level);
	}

	// LOGINFO("m_sigAlrmSCnt = %d, m_sigAlrmLCnt = %d\n", m_sigAlrmSCnt, m_sigAlrmLCnt);
}

/**
    not used.
*/
void startSLAlarm(char outAddr) {
	struct itimerval timer = {{0, TIMER_INTERVAL_US}, {0, TIMER_INTERVAL_US}};
	m_alarmCntTimer = timer;
	signal(SIGALRM, sigAlrmHandle);
	setitimer(ITIMER_REAL, &m_alarmCntTimer, NULL);
	m_alarmSConf.level = true;	// TODO: assume level high alarm active
	m_sigAlrmSCnt = 0;
	m_sigAlrmLCnt = 0;
}

/**
    not used.
*/
void stopSLAlarm(char outAddr) {
	memset(&m_alarmCntTimer, 0, sizeof(struct itimerval));
	setitimer(ITIMER_REAL, &m_alarmCntTimer, NULL);
	m_alarmSConf.level = false;	// TODO: assume level low is alarm deactive
	m_sigAlrmSCnt = 0;
	m_sigAlrmLCnt = 0;
}
/**
    alarm record.
*@param    msgId        ipc message id
*@param    pList        Capturer cfg list data
*@param    id           Capturer id
*@param    recDelay     record extra time,seconds
*@param    recSecond    seconds be record per file
*@return
*      NULL
*/
void startAlmRec(int msgId, Capturer *pList, char id,char recDelay,int recSecond) {
    time_t  tm;
	Capturer *pCapturer = findCapturer(pList, id);
	if (pCapturer != NULL && isCurrInSchemeListRange(pCapturer->pSchemeList)) {
        if(recSecond > ALARM_REC_SECOND_MAX || recSecond < ALARM_REC_SECOND) {
            recSecond = ALARM_REC_SECOND;
        }
        time(&tm);
		RecParam param = {true, id, recSecond + recDelay};
		kmsg_add(msgId, MSGID_ALMHANDLER, MSGID_AV, MSG_ALARM_RECORD, (unsigned char *)&param, sizeof(param));
	}
}
/**
 * alarm send to Client.(upload)
 *@param    msgId       ipc message id
 *@param    sensorAddr  alarm input sensor addr index
 *@param    event       alarm event occur type
 *@param    snapshot    unkown
 *@param    type        alarm result,1:alarm 2:alarm cancel
 *@param    chnId       capturer channel id
 *@param    pTime       alarm time
 *@return
 *      NULL
 */
void sendAlmMsg(int msgId, char sensorAddr, char event, bool snapshot, char type, int chnId, struct tm *pTime) {
	int i;
	AlarmMsg msg;
	char aMsgBuff[MAX_MSG_LEN];
	int msgLen;
	memset(&msg, 0, sizeof(AlarmMsg));

	msg.sensorAddr = sensorAddr;
	timeToBuff(msg.aTime, pTime);
	msg.event = event;
	msg.type = type;

	// alarm
	if (type == ALARM_TYPE_ACTIVE && snapshot) {
		msg.fileNum = 4;
		strcpy(msg.aFtpAddr, SS_FTP_ADDR);
		strcpy(msg.aFtpUser, SS_FTP_USER);
		strcpy(msg.aFtpPwd, SS_FTP_PWD);

		for (i = 0; i < SNAPSHOT_NUM; i++) {
			fillSnapShotFN(&msg.aaFNs[i][0], SNAPSHOT_FN_BUFF_SIZE, chnId, pTime, i);
		}
	}

	msgLen = alarmMsgToBuff(aMsgBuff, MAX_MSG_LEN, &msg);
	kmsg_add(msgId, MSGID_ALMHANDLER, MSGID_NET, MSG_ALARM_MSG, aMsgBuff, msgLen);
	LOGINFO("alarm %s msgLen = %d\n", type == ALARM_TYPE_ACTIVE ? "active" : "deactive", msgLen);
}


/**
 *alarm action
 *@param      msgId       ipc message id
 *@param      channel     base on communication protocol,capture channel number
 *@param      ptzCmd      base on communication protocol,ptz cmd
 *@param      id          base on communication protocol,cmd index
 *@param      preset      preset position,not used.
 *@return
 *          NULL
 */

void startPtzCmd(int msgId, char channel ,char ptzCmd ,unsigned char id,unsigned char preset) {
    uint8   type;
    PTZParam param;
    param.channel = channel;
    param.id    = id;
    param.preset = preset;
    switch(ptzCmd) {
        case 0:     /* preset postion */
            type = MSG_PTZ_CMD;
            param.id = 0x00;
            param.command = 0x00;
            break;
        case 1:     /* preset postion */
            type = MSG_PTZ_PRESET;
            param.command = 0x02;
            break;
        case 2:     /* cruise */
            type = MSG_PTZ_CRUISE;
            param.command = 0x03;
            break;
        case 3:     /* TRACE */
            type = MSG_PTZ_TRACE;
            param.command = 0x03;
            break;
        default:
            return;
    }
	kmsg_add(msgId, MSGID_ALMHANDLER, MSGID_S485, type, (unsigned char *)&param, sizeof(PTZParam) );
}
/**
    alarm snapshot.
*@param    msgId        ipc message id
*@param    id           capturer id
*@param    interval     snapshot per interval seconds
*@param    pTime        record extra time,seconds
*@return
*      NULL
*/
void startSnapShot(int msgId, char id, char interval, struct tm *pTime) {
	SSParam param = {true, id, interval, *pTime};
	kmsg_add(msgId, MSGID_ALMHANDLER, MSGID_AV, MSG_ALARM_SNAP, (unsigned char *)&param, sizeof(param));
}

